package com.rrd.itext.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.itextpdf.text.Element;
import com.itextpdf.text.FontFactoryImp;
import com.itextpdf.text.FontProvider;
import com.itextpdf.text.html.simpleparser.HTMLWorker;
import com.itextpdf.text.html.simpleparser.StyleSheet;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.tool.xml.ElementHandler;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.Writable;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.css.CSSFileWrapper;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.CssFileProcessor;
import com.itextpdf.tool.xml.css.CssFilesImpl;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.exceptions.RuntimeWorkerException;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.WritableElement;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.ElementHandlerPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.rrd.itext.html.ITextServiceCssAppliers;
import com.rrd.itext.html.ITextServiceTags;

public class HTMLParser{
    @Deprecated
    public static List<Element> parseHTML_(String html){
        List<Element> p = new ArrayList<Element>();
        try {  
            StyleSheet st = new StyleSheet();
            st.loadTagStyle("body", "leading", "16,0");
            st.loadTagStyle("ul", "padding", "0 40px");
            st.loadTagStyle("0l", "padding", "0 40px");
            p = HTMLWorker.parseToList(new StringReader(html), st);
        }catch(Exception e) {  
            e.printStackTrace();  
        }
        return p;
    }
    
    public static List<Element> parseHTML(String html, FontProvider fontProvider) throws Exception{
        if(html == null || "".equals(html)){
            return new ArrayList<Element>();
        }
        if(!html.startsWith("<")){
            html = "<p>" + html + "</p>";
        }
        final List<Element> list = new ArrayList<Element>();
        try{
            CssFilesImpl cssFiles = new CssFilesImpl();
            cssFiles.add(getDefaultCSS());
            CSSResolver cssResolver = new StyleAttrCSSResolver(cssFiles);
            ITextServiceCssAppliers cssAppliers = null;
            if(fontProvider != null){
                cssAppliers = new ITextServiceCssAppliers(fontProvider);
            }else{
                cssAppliers = new ITextServiceCssAppliers();
            }
            HtmlPipelineContext hpc = new HtmlPipelineContext(cssAppliers);
            hpc.setAcceptUnknown(true).autoBookmark(true).setTagFactory(ITextServiceTags.getTagFactory());
            ElementHandlerPipeline ehPipeline = new ElementHandlerPipeline(new ElementHandler() {
                public void add(final Writable w) {
                    if (w instanceof WritableElement) {
                        List<Element> elements = ((WritableElement)w).elements();
                        list.addAll(elements);
                    }

                }
            }, null);
            Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(hpc, ehPipeline));
            XMLWorker worker = new XMLWorker(pipeline, true);
            XMLParser p = new XMLParser();
            p.addListener(worker);
            p.parse(new StringReader(html));
        }catch(Exception e){
            list.addAll(parseHTML_(html));
        }
        return list;
    }
    
    public static List<Element> parseHTML(String html) throws Exception{
        return parseHTML(html, null);
    }
    
    public static CssFile getDefaultCSS() {
        CssFile defaultCssFile = null;
            final InputStream in = HTMLParser.class.getResourceAsStream("/default.css");
            if (null != in) {
                final CssFileProcessor cssFileProcessor = new CssFileProcessor();
                int i = -1;
                try {
                    while (-1 != (i = in.read())) {
                        cssFileProcessor.process((char) i);
                    }
                    defaultCssFile = new CSSFileWrapper(cssFileProcessor.getCss(), true);
                } catch (final IOException e) {
                    throw new RuntimeWorkerException(e);
                } finally {
                    try {
                        in.close();
                    } catch (final IOException e) {
                        throw new RuntimeWorkerException(e);
                    }
                }
            }
        return defaultCssFile;
    }
    
    public static String htmlUnescape(String html){
        if(html == null){
            return "";
        }
        String content = new String(html);

        content = content.replaceAll("&lt;", "<");
        content = content.replaceAll("&gt;", ">");
        content = content.replaceAll("&nbsp;", " ");
        content = content.replaceAll("&amp;", "&");
        content = content.replaceAll("&quot;", "\"");
        
        return content;
    }
    
    
    public static void main(String[] args){
        System.out.println(HTMLParser.class.getResource(""));
    }
}
